package test.t1;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

/**
 * 图像验证码生成器
 */
public class CaptchaGenerator {

    private static final int WIDTH = 120;
    private static final int HEIGHT = 40;
    private static final int CHAR_LENGTH = 5; // 验证码长度
    private static final String LETTER_SET = "ABCDEFGHJKLMNPQRSTUVWXYZ"; // 去除易混淆字符 O/0, I/1, L
    private static final String DIGIT_SET = "23456789"; // 数字（去除了0,1）
    private static Random random = new Random();

    /**
     * 生成验证码
     * @return Captcha 对象
     */
    public static Captcha generate() {
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();
        StringBuilder sb = new StringBuilder();

        try {
            // 启用抗锯齿，让扭曲更平滑
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

            // 设置背景色：浅灰到白色渐变
            GradientPaint gp = new GradientPaint(0, 0, getRandColor(220, 250), 0, HEIGHT, getRandColor(230, 255));
            g.setPaint(gp);
            g.fillRect(0, 0, WIDTH, HEIGHT);

            // 字符绘制起始x坐标
            int x = 10;

            // 步骤1：生成字符（最多2个数字）
            List<Character> chars = generateCharsWithLimitedDigits();

            // 步骤2：逐个绘制字符，增加扭曲和大小变化
            for (char ch : chars) {
                sb.append(ch);

                // 随机颜色（深色为主）
                g.setColor(getRandColor(20, 150));

                int fontSize = 15 + random.nextInt(10);
                Font font = new Font("Arial",
                        random.nextBoolean() ? Font.BOLD : Font.ITALIC,
                        fontSize);
                g.setFont(font);

                // --- 关键：增强扭曲 ---
                AffineTransform transform = new AffineTransform();

                // 随机旋转（比之前更大角度）
                double angle = (random.nextDouble() - 0.5) * 0.5; // -0.25 ~ +0.25 弧度
                // 随机缩放（轻微拉伸）
                double scale = 0.9 + random.nextDouble() * 0.3; // 0.9 ~ 1.2
                // 随机倾斜（shear）
                double shear = random.nextDouble();

                transform.rotate(angle, x + 30, 30);
//                transform.scale(scale, scale);
//                transform.shear(shear, 0); // 水平剪切

                g.setTransform(transform);

                // 绘制字符
                g.drawString(String.valueOf(ch), x, 25); // y坐标也随机微调

                // 字符间距随机
                x += 20;
            }

            // 恢复默认变换
            g.setTransform(new AffineTransform());

            // 添加干扰线（彩色、更粗）
            for (int i = 0; i < 10; i++) {
                g.setColor(getRandColor(150, 200));
                Stroke oldStroke = g.getStroke();
                g.setStroke(new BasicStroke(1.5f)); // 线条稍粗
                g.drawLine(random.nextInt(WIDTH), random.nextInt(HEIGHT),
                        random.nextInt(WIDTH), random.nextInt(HEIGHT));
                g.setStroke(oldStroke);
            }

            // 添加噪点
            for (int i = 0; i < 100; i++) {
                int xPoint = random.nextInt(WIDTH);
                int yPoint = random.nextInt(HEIGHT);
                g.setColor(getRandColor(180, 220));
                g.fillOval(xPoint, yPoint, 1, 1);
            }
        } finally {
            g.dispose(); // 重要：释放资源
        }

        return new Captcha(sb.toString(), image);
    }

    /**
     * 生成字符列表，确保数字不超过2个
     */
    private static List<Character> generateCharsWithLimitedDigits() {
        List<Character> result = new ArrayList<>();
        int digitCount = 0;
        int maxDigits = 2;

        for (int i = 0; i < CHAR_LENGTH; i++) {
            boolean wantDigit = digitCount < maxDigits && random.nextDouble() < 0.4; // 40%概率尝试加数字

            if (wantDigit && random.nextBoolean()) {
                result.add(DIGIT_SET.charAt(random.nextInt(DIGIT_SET.length())));
                digitCount++;
            } else {
                // 加大写字母
                result.add(LETTER_SET.charAt(random.nextInt(LETTER_SET.length())));
            }
        }

        // 打乱顺序，避免数字集中在前面
        Collections.shuffle(result);
        return result;
    }

    /**
     * 输出验证码图片到流（用于Web）
     * @param captcha 验证码对象
     * @param out 输出流
     * @throws Exception
     */
    public static void output(Captcha captcha, OutputStream out) throws Exception {
        ImageIO.write(captcha.getImage(), "JPEG", out);
    }

    /**
     * 生成随机颜色
     */
    private static Color getRandColor(int fc, int bc) {
        if (fc > 255) fc = 255;
        if (bc > 255) bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    // --- 测试方法 ---
    public static void main(String[] args) throws Exception {
        Captcha captcha = generate();
        System.out.println("生成的验证码: " + captcha.getText());
        
        // 保存到文件测试
        java.io.FileOutputStream fos = new java.io.FileOutputStream("captcha.jpg");
        output(captcha, fos);
        fos.close();
        System.out.println("验证码已保存为 captcha.jpg");
    }
}